package testpackage.threadpool;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;

public class ThreadPoolStudy {
    private ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(4, 8, 10000L,
            TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(40, false), new ThreadPoolExecutor.CallerRunsPolicy());

    private static long calculateNum = 124240000234L;

    public static void main(String[] args) {
        new Thread(() -> {
            long result = new ThreadPoolStudy().execute(calculateNum);
            System.out.println(result);
        }).start();

        new Thread(() -> {
            System.out.println("single thread execute start" + System.currentTimeMillis());
            long result = 0;
            for (long i = 0; i < calculateNum; i++) {
                result += i;
            }
            System.out.println(result);
            System.out.println("single thread execute end " + System.currentTimeMillis());
        }).start();

    }

    private Long execute(Long countNum) {
        System.out.println("multiThread execute start" + System.currentTimeMillis());
        List<Future<Long>> list = new ArrayList<>();

        list.sort((o1, o2) -> 0);
        Arrays.sort(list.toArray());
        Collections.sort(list, (o1, o2) -> 0);


        if (countNum < 10000L) {
            return Long.MIN_VALUE;
        }



        long eighePercentOne = countNum / 8;
        for (int i = 0; i < 7; i++) {

            Future<Long> future = poolExecutor.submit(new Task(eighePercentOne * i, eighePercentOne * (i + 1)));
            list.add(future);
        }

        list.add(poolExecutor.submit(new Task(eighePercentOne * 7, countNum)));
        long out = 0;
        for (Future<Long> future : list) {
            try {
                out += future.get();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        System.out.println("multi thread execute end" + System.currentTimeMillis());
        return out;

    }


    static class Task implements Callable<Long> {

        private Long from;
        private Long end;

        Task(Long from, Long end) {
            this.from = from;
            this.end = end;
        }

        @Override
        public Long call() {
            long result = 0;
            for (long i = from; i < end; i++) {
                result += i;
            }
            return result;
        }
    }
}
